home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 2
/
CU Amiga Magazine's Super CD-ROM 02 (1996)(EMAP Images)(GB)[!][issue 1996-04].iso
/
magazine
/
amiga_e
/
yax
/
yax.e
< prev
Wrap
Text File
|
1992-09-02
|
29KB
|
952 lines
/* YAX (Yet Another Instruction Code Set) Interpreter v1.2
simple procedural/(functional) language with lisp-lookalike syntax.
eats sources with extension .yax for dinner. */
/* v1.2 now includes as mass of new functions! see doc. at end of source */
OPT STACK=25000 /* we do heavy recursion */
OBJECT var /* this is where we store our runtime values */
type:INT
name:LONG
value:LONG
ENDOBJECT
/* intermed'
iate codes */
ENUM ENDSOURCE,VALUE,ISTRING,IDENT,LBRACKET,RBRACKET
/* keywords */
ENUM FWRITE=100,FADD,FEQ,FUNEQ,FSUB,FMUL,FDIV,FAND,FORX,FNOT,FIF,FDO,
FSELECT,FSET,FFOR,FWHILE,FUNTIL,FDEFUN,FLAMBDA,FAPPLY,FREADINT,
FARRAY,FGREATER,FSMALLER,FLOCATE,FCLS,FDUMP,FWINDOW,FTELL,FTOLD,
FSEE,FSEEN,FSTRING,FREAD,FGET,FPUT,FFILELEN,FLINE,FPLOT,FBOX,
FMOUSEX,FMOUSEY,FMOUSE,FTEXT,FABS,FMOD,FEOR,FSWAP,FPOWER,FREQ,
FINC,FDEC,FRND,FRNDQ,FKICK,FWHEN,FELSE,FWIN,FSCREEN,FMESSAGE,
FGADGET,FGADNUM,FHEX,FEXIT,LAST
CONST KEYWORDSIZE=8,
NRKEYWORDS=LAST-99,
IDENTNAMESPACE=30000,
VARSTACKSPACE=50000,
MAXARGS=5,
ERLEN=60
/* errors */
ENUM ER_WORKSPACE=1,ER_BUF,ER_GARBAGE,ER_SYNTAX,ER_EXPKEYWORD,ER_EXPRBRACKET,
ER_EXPEXP,ER_QUOTE,ER_COMMENT,ER_INFILE,ER_SOURCEMEM,ER_EXPIDENT,
ER_ARGS,ER_TYPE,ER_EXPLBRACKET,ER_STACK,ER_ALLOC,ER_ARRAY,ER_FILE,
ER_GFXWIN,ER_VALUES,ER_KICK
/* variable types */
ENUM TINTEGER=1,TSTRING,TFUNC,TARRAY
DEF source,slen,erpos=NIL,
ilen,ibuf,ipos:PTR TO INT,p:PTR TO INT,idents,
name[100]:STRING,wfile,
inputbuf[100]:STRING,winspec[100]:STRING,
vartop,varbottom,vars,rec,globvar,
infile,outfile,oldout,oldin,stdin,
gfxwindow=NIL,curwindow=NIL,curscreen=NIL,gadnum=-1
PROC main()
WriteF(''); stdin:=stdout
loadsource()
ilen:=Mul(slen,4)+1000 /* guess the needed workspace */
ibuf:=New(ilen+10)
idents:=String(IDENTNAMESPACE)
vars:=New(VARSTACKSPACE)
vartop:=vars; varbottom:=vars
IF (ibuf=NIL) OR (idents=NIL) OR (vars=NIL)
error(ER_WORKSPACE)
ELSE
lexanalyse() /* translate to intermediate format */
p:=ibuf
WHILE p[]<>ENDSOURCE DO eval() /* run the code */
ENDIF
error(0)
ENDPROC
PROC lexanalyse()
DEF pos,end,c,count,ident[50]:STRING,pos2,keypos,a,nr,ident2[50]:STRING
pos:=source; end:=pos+slen; ipos:=ibuf; erpos:=pos
StrCopy(idents,' ',1)
loop:
c:=pos[]++
IF c>96 /* an identifier */
pos2:=pos-1
WHILE pos[]++>96 DO NOP; DEC pos
StrCopy(ident,pos2,pos-pos2)
StrCopy(ident2,ident,ALL)
StrAdd(ident,'..............',ALL)
keypos:={keywords}
nr:=0
FOR a:=1 TO NRKEYWORDS /* lookup keywords */
IF StrCmp(ident,keypos,KEYWORDSIZE)
nr:=99+a
JUMP found
ENDIF
keypos:=keypos+KEYWORDSIZE
ENDFOR
found:
IF nr>0 /* keyword */
iword(nr)
ELSE /* own identifier */
iword(IDENT)
StrCopy(ident,' ',1)
StrAdd(ident,ident2,ALL)
StrAdd(ident,' ',1)
pos2:=InStr(idents,ident,0)
IF pos2=-1
ilong(EstrLen(idents)+idents)
StrAdd(idents,ident2,ALL)
StrAdd(idents,' ',1)
IF EstrLen(idents)=StrMax(idents) THEN error(ER_WORKSPACE)
ELSE
ilong(pos2+idents+1)
ENDIF
ENDIF
ELSE
SELECT c /* anything else */
CASE " "
IF pos<end THEN JUMP loop
CASE "("
iword(LBRACKET)
erpos:=pos-1
ilong(erpos)
CASE ")"; iword(RBRACKET)
CASE "+"; iword(FADD)
CASE "-"
IF pos[]=" "
iword(FSUB)
ELSE
iword(VALUE)
ilong(-Val(pos,{c}))
IF c=0 THEN error(ER_GARBAGE) ELSE pos:=pos+c
ENDIF
CASE "*"; iword(FMUL)
CASE "/"
IF pos[]<>"*"
iword(FDIV)
ELSE /* comment (like this one) */
INC pos
WHILE pos-1<end
INC count
IF (pos[]++="*") AND (pos[]="/") THEN JUMP out
ENDWHILE
error(ER_COMMENT)
out:
INC pos
ENDIF
CASE "="
iword(FEQ)
CASE ">"
iword(FGREATER)
CASE "<"
iword(FSMALLER)
CASE "?"
iword(FUNEQ)
CASE "'" /* string constant */
iword(ISTRING)
count:=0; pos2:=pos
WHILE pos[]++<>"'"
INC count
IF pos=end THEN error(ER_QUOTE)
ENDWHILE
iword(count)
ilong(pos2) /* char adress */
CASE 10
IF pos<end THEN JUMP loop
CASE 0
pos:=end
CASE 9
IF pos<end THEN JUMP loop
DEFAULT
iword(VALUE)
ilong(Val(pos--,{c}))
IF c=0 THEN error(ER_GARBAGE) ELSE pos:=pos+c
ENDSELECT
ENDIF
IF pos<end THEN JUMP loop
iword(ENDSOURCE)
ENDPROC
PROC checkstop()
IF FreeStack()<1000 THEN error(ER_STACK)
IF CtrlC() THEN error(-1)
ENDPROC
PROC eval() /* main recursive evaluation function */
DEF r=0,i,ins,p2,x:PTR TO LONG,a,adr:PTR TO var
checkstop()
i:=p[]++
SELECT i
CASE VALUE
r:=^p++
CASE IDENT
r:=varvalue(^p++,TINTEGER)
CASE LBRACKET
erpos:=^p++
ins:=p[]++
IF ins=IDENT
adr:=findvar(^p++)
IF adr.type=TFUNC
r:=dofunc(adr.value)
ELSE
IF adr.type<>TARRAY THEN error(ER_TYPE)
x:=adr.value
a:=eval()
IF (a<0) OR (a>x[]) THEN error(ER_ARRAY)
r:=x[a+1]
ENDIF
ELSE
IF ins<100 THEN error(ER_EXPKEYWORD)
SELECT ins
CASE FWRITE /* output string constants + expressions */
x:=TRUE
WHILE p[]<>RBRACKET
IF p[]=ISTRING
Write(stdout,Long(p+4),p[1])
IF (p[1]=0) AND (p[4]=RBRACKET) THEN x:=FALSE
p:=p+8
ELSEIF p[]=IDENT
IF (Int(findvar(Long(p+2)))=TSTRING)
WriteF('\s',eatstring())
ELSE
WriteF('\d',eval())
ENDIF
ELSE
WriteF('\d',eval())
ENDIF
ENDWHILE
IF x THEN WriteF('\n')
CASE FEQ
r:=TRUE
x:=eval()
WHILE p[]<>RBRACKET DO IF x<>eval() THEN r:=FALSE
CASE FUNEQ; r:=eval()<>eval()
CASE FGREATER; r:=eval()>eval()
CASE FSMALLER; r:=eval()<eval()
CASE FADD; r:=eval(); WHILE p[]<>RBRACKET DO r:=r+eval()
CASE FSUB; r:=eval(); WHILE p[]<>RBRACKET DO r:=r-eval()
CASE FMUL; r:=eval(); WHILE p[]<>RBRACKET DO r:=Mul(r,eval())
CASE FDIV; r:=eval(); WHILE p[]<>RBRACKET DO r:=r/eval()
CASE FAND; r:=eval(); WHILE p[]<>RBRACKET DO r:=r AND eval()
CASE FORX; r:=eval(); WHILE p[]<>RBRACKET DO r:=r OR eval()
CASE FEOR; r:=eval(); WHILE p[]<>RBRACKET DO r:=Eor(r,eval())
CASE FNOT; r:=Not(eval())
CASE FABS; r:=Abs(eval())
CASE FRND; r:=Rnd(eval())
CASE FRNDQ; r:=RndQ(eval())
CASE FKICK; r:=KickVersion(eval())
CASE FMOD; r:=Mod(eval(),eval())
CASE FWHEN
IF eval()
WHILE (p[]<>FELSE) AND (p[]<>RBRACKET) DO r:=eval()
IF p[]=FELSE
p++
WHILE (p[]<>RBRACKET) DO skip()
ENDIF
ELSE
WHILE (p[]<>FELSE) AND (p[]<>RBRACKET) DO skip()
IF p[]=FELSE
p++
WHILE (p[]<>RBRACKET) DO r:=eval()
ENDIF
ENDIF
CASE FIF
IF eval()
r:=eval()
IF p[]<>RBRACKET THEN skip()
ELSE
skip()
IF p[]<>RBRACKET THEN r:=eval()
ENDIF
CASE FDO; WHILE p[]<>RBRACKET DO r:=eval()
CASE FSELECT
x:=eval()
WHILE p[]<>RBRACKET DO IF x=eval() THEN r:=eval() ELSE skip()
CASE FSET
IF p[]=LBRACKET
p:=p+2
erpos:=^p++
x:=varvalue(eatident(),TARRAY)
a:=eval()
IF (a<0) OR (a>x[0]) THEN error(ER_ARRAY)
IF p[]++<>RBRACKET THEN error(ER_EXPRBRACKET)
x[a+1]:=eval()
ELSE
x:=eatident()
IF (p[]=LBRACKET) AND (p[3]=FLAMBDA)
p:=p+8
adr:=findvar(x)
letvar(adr,p,TFUNC)
WHILE p[]<>RBRACKET DO skip()
p:=p+2
ELSEIF p[]=ISTRING
r:=eatstring()
x:=findvar(x)
letvar(x,r,TSTRING)
ELSE
r:=eval()
x:=findvar(x)
letvar(x,r,TINTEGER)
ENDIF
ENDIF
CASE FINC
x:=eatident()
r:=varvalue(x,TINTEGER)
x:=findvar(x)
letvar(x,r+1,TINTEGER)
CASE FDEC
x:=eatident()
r:=varvalue(x,TINTEGER)
x:=findvar(x)
letvar(x,r-1,TINTEGER)
CASE FSWAP
x:=eatident()
r:=varvalue(x,TINTEGER)
x:=findvar(x)
adr:=eatident()
a:=varvalue(adr,TINTEGER)
adr:=findvar(adr)
letvar(x,a,TINTEGER)
letvar(adr,r,TINTEGER)
r:=0
CASE FPOWER
r:=adr:=eval()
x:=eval()
IF x>1 THEN FOR a:=2 TO x DO r:=r*adr
CASE FFOR
x:=eatident()
r:=eval()
adr:=findvar(x)
x:=eval()
p2:=p
IF r>x /* downto */
FOR a:=r TO x STEP -1
p:=p2
letvar(adr,a,TINTEGER)
WHILE p[]<>RBRACKET DO eval()
ENDFOR
ELSE
FOR a:=r TO x
p:=p2
letvar(adr,a,TINTEGER)
WHILE p[]<>RBRACKET DO eval()
ENDFOR
ENDIF
r:=0
CASE FWHILE
p2:=p
WHILE eval()
WHILE p[]<>RBRACKET DO eval()
p:=p2
ENDWHILE
WHILE p[]<>RBRACKET DO skip()
r:=0
CASE FUNTIL
p2:=p
WHILE eval()=FALSE
WHILE p[]<>RBRACKET DO eval()
p:=p2
ENDWHILE
WHILE p[]<>RBRACKET DO skip()
r:=0
CASE FDEFUN
x:=eatident()
adr:=findvar(x)
letvar(adr,p,TFUNC)
WHILE p[]<>RBRACKET DO skip()
CASE FLAMBDA; error(ER_SYNTAX)
CASE FAPPLY
IF p[]<>IDENT
IF (p[]<>LBRACKET) OR (p[3]<>FLAMBDA) THEN error(ER_EXPIDENT)
p:=p+8; adr:=p
WHILE p[]<>RBRACKET DO skip()
p:=p+2
r:=dofunc(adr)
ELSE
p:=p+2
r:=dofunc(varvalue(^p++,TFUNC))
ENDIF
CASE FREADINT
IF ReadStr(stdin,inputbuf)=-1
r:=0
ELSE
r:=Val(inputbuf,{x})
ENDIF
CASE FARRAY
adr:=findvar(eatident())
a:=eval()
x:=New(Mul(a,4)+8)
IF x=NIL THEN error(ER_ALLOC)
letvar(adr,x,TARRAY)
x[]++:=a
WHILE (p[]++=VALUE)
IF a-->=0 THEN x[]++:=^p++ ELSE p:=p+4
ENDWHILE
p--
CASE FLOCATE; WriteF('\e[\d;\dH',eval(),eval())
CASE FCLS; Out(stdout,12)
CASE FDUMP
adr:=varbottom
WriteF('\n')
WHILE adr<vartop
a:=adr.name
x:=a
WHILE Char(x)<>" " DO INC x
Write(stdout,a,x-a)
x:=adr.type
SELECT x
CASE TINTEGER; WriteF(' = \d (int)\n',adr.value)
CASE TSTRING; WriteF(' = "\s" (string)\n',adr.value)
CASE TFUNC; WriteF(' (function)\n')
CASE TARRAY; WriteF('[\d] (array)\n',Long(adr.value))
ENDSELECT
adr:=adr+SIZEOF var
ENDWHILE
WriteF('\n')
CASE FWINDOW
StringF(winspec,'CON:\d/\d/\d/\d/',eval(),eval(),eval(),eval())
x:=eatstring()
StrAdd(winspec,x,ALL)
wfile:=Open(winspec,1006)
IF wfile=NIL THEN error(ER_FILE)
IF conout<>NIL THEN Close(conout)
stdout:=wfile
conout:=stdout
stdin:=stdout
adr:=OpenWorkBench()
Forbid()
a:=NIL
IF adr<>NIL
adr:=Long(adr+4)
WHILE (adr<>NIL) AND (a=NIL)
IF StrCmp(x,Long(adr+32),ALL) THEN a:=adr
adr:=^adr
ENDWHILE
ENDIF
Permit()
IF a THEN gfxwindow:=a
CASE FREQ
IF KickVersion(37)=FALSE THEN error(ER_KICK)
r:=EasyRequestArgs(IF curwindow THEN curwindow ELSE NIL,
[20,0,eatstring(),eatstring(),eatstring()],0,NIL)
CASE FTELL
IF outfile<>NIL THEN Close(outfile)
outfile:=NIL
outfile:=Open(eatstring(),1006)
IF outfile=NIL THEN error(ER_FILE)
oldout:=stdout
stdout:=outfile
CASE FTOLD
IF outfile<>NIL THEN Close(outfile)
outfile:=NIL
stdout:=oldout
CASE FSEE
IF infile<>NIL THEN Close(infile)
infile:=NIL
infile:=Open(eatstring(),1005)
IF infile=NIL THEN error(ER_FILE)
oldin:=stdin
stdin:=infile
CASE FSEEN
IF infile<>NIL THEN Close(infile)
infile:=NIL
stdin:=oldin
CASE FSTRING
adr:=String(250)
IF adr=NIL THEN error(ER_ALLOC)
letvar(findvar(eatident()),adr,TSTRING)
CASE FREAD
x:=varvalue(eatident(),TSTRING)
r:=ReadStr(stdin,x)
CASE FGET; r:=Inp(stdin)
CASE FPUT; r:=eval(); IF r<>-1 THEN Out(stdout,r)
CASE FFILELEN
r:=FileLength(eatstring())
IF r=-1 THEN r:=0
CASE FLINE; getrast(); Line(eval(),eval(),eval(),eval(),eval())
CASE FPLOT; getrast(); Plot(eval(),eval(),eval())
CASE FBOX
getrast()
a:=eval(); x:=eval(); p2:=eval(); r:=eval()
IF a>p2
adr:=a; a:=p2; p2:=adr
ENDIF
IF x>r
adr:=x; x:=r; r:=adr
ENDIF
IF (a<0) OR (x<0) OR (p2>10000) OR (r>10000) THEN error(ER_VALUES)
Box(a,x,p2,r,eval())
r:=0
CASE FMOUSEX; r:=MouseX(getwin())
CASE FMOUSEY; r:=MouseY(getwin())
CASE FMOUSE; r:=Mouse()
CASE FTEXT
adr:=getrast()
a:=eval(); x:=eval()
Colour(eval(),eval())
TextF(a,x,eatstring())
r:=0
CASE FMESSAGE
r:=WaitIMessage(getwin())
gadnum:=IF (r=$20) OR (r=$40) THEN Long(MsgIaddr()+40) ELSE -1
CASE FGADNUM
r:=gadnum
CASE FGADGET
IF (adr:=New(GADGETSIZE))=NIL THEN error(ER_ALLOC)
Gadget(adr,NIL,eval(),0,eval(),eval(),eval(),eatstring())
AddGadget(getwin(),adr,-1)
RefreshGList(adr,getwin(),NIL,1)
CASE FSCREEN
CloseS(curscreen)
curscreen:=NIL
curscreen:=OpenS(eval(),eval(),eval(),eval(),eatstring())
CASE FWIN
CloseW(curwindow)
curwindow:=NIL
gfxwindow:=NIL
curwindow:=OpenW(eval(),eval(),eval(),eval(),
eval(),eval(),eatstring(),
IF curscreen THEN curscreen ELSE NIL,
IF curscreen THEN 15 ELSE 1,NIL)
gfxwindow:=curwindow
CASE FHEX
WriteF('$\z\h[8]',eval())
CASE FEXIT
error(0)
ENDSELECT
ENDIF
IF p[]++<>RBRACKET THEN error(ER_EXPRBRACKET)
DEFAULT
IF (i=RBRACKET) OR (i=ISTRING) THEN error(ER_EXPEXP) ELSE error(ER_SYNTAX)
ENDSELECT
ENDPROC r
PROC getwin()
IF gfxwindow=NIL THEN error(ER_GFXWIN)
ENDPROC gfxwindow
PROC getrast()
DEF r
IF curwindow=NIL
IF curscreen=NIL
IF gfxwindow=NIL THEN error(ER_GFXWIN)
r:=Long(gfxwindow+50)
ELSE
r:=curscreen+84
ENDIF
ELSE
r:=Long(curwindow+50)
ENDIF
SetStdRast(r)
ENDPROC r
PROC eatstring()
DEF adr,x
IF p[]=ISTRING
p:=p+2; x:=p[]++; adr:=^p++
adr[x]:=0
ELSE
adr:=varvalue(eatident(),TSTRING)
ENDIF
ENDPROC adr
PROC eatident()
IF p[]++<>IDENT THEN error(ER_EXPIDENT)
ENDPROC ^p++
PROC dofunc(lcode)
DEF args[MAXARGS]:ARRAY OF LONG,a=0,oldvarb,oldvart,oldp,x,r=0,olderpos
checkstop()
WHILE p[]<>RBRACKET
IF a=MAXARGS THEN error(ER_ARGS)
args[a]:=eval()
INC a
ENDWHILE
IF rec=0 THEN globvar:=vartop
oldvarb:=varbottom; varbottom:=vartop; oldvart:=vartop;
oldp:=p; p:=lcode; olderpos:=erpos; INC rec
IF p[]++<>LBRACKET THEN error(ER_EXPLBRACKET)
erpos:=^p++
WHILE p[]<>RBRACKET
IF a=0 THEN error(ER_ARGS)
x:=findvar(eatident())
letvar(x,args[]++,TINTEGER)
DEC a
ENDWHILE
IF a<>0 THEN error(ER_ARGS)
p:=p+2
WHILE p[]<>RBRACKET DO r:=eval()
varbottom:=oldvarb; vartop:=oldvart; p:=oldp; erpos:=olderpos; DEC rec
ENDPROC r
PROC findvar(id)
DEF loc=0:PTR TO var,a:PTR TO var
IF vartop<>varbottom
a:=varbottom /* check existing local vars */
WHILE (a<vartop) AND (loc=0)
IF a.name=id THEN loc:=a
a:=a+SIZEOF var
ENDWHILE
ENDIF
IF loc=0
IF (rec>0) AND (globvar>vars) /* check global vars */
a:=vars
WHILE (a<globvar) AND (loc=0)
IF a.name=id THEN loc:=a
a:=a+SIZEOF var
ENDWHILE
ENDIF
IF loc=0 /* create new var dynamically */
loc:=vartop
vartop:=vartop+SIZEOF var
IF vars+VARSTACKSPACE<vartop THEN error(ER_WORKSPACE)
loc.type:=TINTEGER
loc.name:=id
loc.value:=0
ENDIF
ENDIF
ENDPROC loc
PROC letvar(adr:PTR TO var,value,type)
IF (adr.type<>type) AND (adr.type<>TINTEGER) THEN error(ER_TYPE)
checkstop()
adr.type:=type
adr.value:=value
ENDPROC
PROC varvalue(id,type)
DEF adr:PTR TO var
checkstop()
adr:=findvar(id)
IF adr.type<>type THEN error(ER_TYPE)
ENDPROC adr.value
PROC skip() /* skip *one* expression */
DEF deep=0,i
REPEAT
i:=p[]++
IF (i=VALUE) OR (i=LBRACKET) OR (i=IDENT) THEN p:=p+4
IF i=ISTRING THEN p:=p+6
IF i=LBRACKET THEN INC deep
IF i=RBRACKET THEN IF deep=0 THEN error(ER_EXPEXP) ELSE DEC deep
IF i=ENDSOURCE THEN error(ER_EXPRBRACKET)
UNTIL deep=0
ENDPROC
PROC iword(x)
IF ibuf+ilen>ipos THEN ipos[]++:=x ELSE error(ER_BUF)
ENDPROC
PROC ilong(x)
IF ibuf+ilen>ipos THEN ^ipos++:=x ELSE error(ER_BUF)
ENDPROC
PROC loadsource()
DEF suxxes=FALSE,handle,read
IF StrCmp(arg,'?',ALL) OR StrCmp(arg,'',ALL)
WriteF('USAGE: Yax <source> (default ext. ".yax")\n')
error(0)
ELSE
StrCopy(name,arg,ALL)
StrAdd(name,'.yax',4)
slen:=FileLength(name)
handle:=Open(name,1005)
IF (handle=NIL) OR (slen=-1)
error(ER_INFILE)
ELSE
source:=New(slen+10)
IF source=NIL
error(ER_SOURCEMEM)
ELSE
read:=Read(handle,source,slen)
Close(handle)
IF read=slen
suxxes:=TRUE
source[slen]:=0
ELSE
error(ER_INFILE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC error(nr)
DEF erstr[ERLEN]:STRING,a
IF outfile
IF stdout=outfile THEN stdout:=oldout
Close(outfile)
ENDIF
IF infile
IF stdin=infile THEN stdin:=oldin
Close(infile)
ENDIF
CloseW(curwindow)
CloseS(curscreen)
WriteF('\n')
IF nr>0
WriteF('ERROR: ')
SELECT nr
CASE ER_WORKSPACE; WriteF('Could not allocate workspace!\n')
CASE ER_BUF; WriteF('Buffer overflow!\n')
CASE ER_GARBAGE; WriteF('Garbage in line\n')
CASE ER_SYNTAX; WriteF('Your syntax sucks\n')
CASE ER_EXPKEYWORD; WriteF('Keyword identifier expected\n')
CASE ER_EXPRBRACKET; WriteF('Right bracket expected\n')
CASE ER_EXPEXP; WriteF('Evaluateable expression expected\n')
CASE ER_QUOTE; WriteF('Missing quote \a\n')
CASE ER_COMMENT; WriteF('Missing "*/"\n')
CASE ER_SOURCEMEM; WriteF('No Memory for source!\n')
CASE ER_INFILE; WriteF('Could not open file "\s".\n',name)
CASE ER_EXPIDENT; WriteF('Identifier expected\n')
CASE ER_ARGS; WriteF('Illegal #of arguments\n')
CASE ER_TYPE; WriteF('Wrong type of variable/expression\n')
CASE ER_EXPLBRACKET; WriteF('Left bracket expected\n')
CASE ER_STACK; WriteF('Nearly stack overflow: \d deep\n',rec)
CASE ER_ALLOC; WriteF('Dynamic allocation failed!\n')
CASE ER_ARRAY; WriteF('Array index out of bounds\n')
CASE ER_FILE; WriteF('File error\n')
CASE ER_GFXWIN; WriteF('No User-window for graphics\n')
CASE ER_VALUES; WriteF('Illegal value(s)\n')
CASE ER_KICK; WriteF('You need OS 37+ for this function\n')
ENDSELECT
IF erpos<>NIL
StrCopy(erstr,erpos,ALL)
FOR a:=0 TO ERLEN-1 DO IF erstr[a]=10 THEN erstr[a]:=32
WriteF('NEARBY: \s\n',erstr)
ENDIF
ELSEIF nr=-1
WriteF('*** Program halted.\n')
ENDIF
IF conout<>NIL THEN WriteF('Press <return> to continue ...\n')
CleanUp(0)
ENDPROC
keywords:
CHAR 'write...', 'add.....', 'eq......', 'uneq....', 'sub.....',
'mul.....', 'div.....', 'and.....', 'or......', 'not.....',
'if......', 'do......', 'select..', 'set.....', 'for.....',
'while...', 'until...', 'defun...', 'lambda..', 'apply...',
'readint.', 'array...', 'greater.', 'smaller.', 'locate..',
'cls.....', 'dump....', 'window..', 'tell....', 'told....',
'see.....', 'seen....', 'string..', 'read....', 'get.....',
'put.....', 'filelen.', 'line....', 'plot....', 'box.....',
'mousex..', 'mousey..', 'mouse...', 'text....', 'abs.....',
'mod.....', 'eor.....', 'swap....', 'power...', 'req.....',
'inc.....', 'dec.....', 'rnd.....', 'rndq....', 'kick....',
'when....', 'else....', 'win.....', 'screen..', 'message.',
'gadget..', 'gadid...', 'hex.....', 'exit....'
/* doc file follows: (see end of doc for new v1.2 functions) */
/* +---------------------------------------+
| |
| Amiga YAX Interpreter v1.1 |
| |
| (c) 1992/93 $#%! |
| M A N U A L |
| |
+---------------------------------------+
1. Introduction
2. The Language
3. Built-in Functions
+---------------------------------------+
| 1. Introduction |
+---------------------------------------+
update from v0.x/1.0 to 1.1:
bug fixes:
- negative number division failed!
- box accepted illegal values
update from v1.1 to 1.2:
- new functions, see below.
YAX stands for "Yet Another Instruction Code Set", as the author couldn't
think of better name. YAX is a procedural language with LISP-syntax and
evaluation, as well as somewhat lambda function application.
In this manual it is assumed the reader possesses knowledge of other
languages, as all 'obvious' explanations are left out. Readers for whom
YAX would be their first programming language are advised to read
a standard text on the subject 8-).
+---------------------------------------+
| 2. The Language |
+---------------------------------------+
Structure.
The basic building block of a YAX program is called a term.
Examples of terms are:
integer constants: 1 2 100 -1
string constants: 'a' 'hi folks!'
variables: a count
function calls: (+ 1 2) (* 3 (- 4 5))
a function call is a list '()' with as first item the name of the
function to be applied, followed by its arguments. With few execeptions,
arguments to functions are again terms, so expressions may be built
to infinite complexity. The main task of the interpreter is to
evaluate these terms recursively.
Format.
between any two lexical elements, any number of spaces, tabs and linefeeds
may be placed. Comments start with '/*' and end with '*/', may extend
over several lines, and may be nested. following two statements are equal:
(if(eq a 1)(for b 1 10(write'blabla'))) /* ugly */
(if (eq a 1)
(for b 1 10 (write 'blabla')) /* better */
)
+---------------------------------------+
| 3. Built-in Functions |
+---------------------------------------+
If not explicitly stated, functions return 0. type of arguments:
<term> any term
<iterm> term that evaluates to integer
<sterm> term that evaluates to string
<var> term that is a variable
<svar> term that is a string variable
<func> term that evaluates to a function
... any number of terms of the same type may follow
--> INTEGER MATH <--
(add <iterm> ...) or (+ <iterm> ...)
(sub <iterm> ...) or (- <iterm> ...)
(mul <iterm> ...) or (* <iterm> ...)
(div <iterm> ...) or (/ <iterm> ...)
(and <iterm> ...)
(or <iterm> ...)
(not <iterm>)
(eq <iterm> ...)
(uneq <iterm> <iterm>)
(smaller <iterm> <iterm>)
(greater <iterm> <iterm>)
These functions perform the functions you'd expect them to do.
All boolean logic functions return true (-1) or false (0). and/or/not
work as logical as well as bitwise operators.
except for the last three, all functions handle any number of arguments,
i.e. (eq 10 (+ 1 2 3 4) (* 2 5)) is a valid term.
--> PROGRAM STRUCTURE <--
(for <var> <iterm> <iterm> <term> ...)
(if <boolexp> <ifterm> <elseterm>)
/* also returns value of term */
(do <term> ...)
(select <iterm> <term> ...)
/* <iterm> is matched agains even items of <term>s, and
corresponding odd <term> is executed */
(while <term> <term> ...)
(until <term> <term> ...)
(set <var> <term>)
(defun <var> (<var> ...) <term> ...)
(lambda (var ...) <term> ...)
/* returns function as value (may only be used in (set) and (apply) */
(apply <func> <term> ...)
(array <var> <iterm>)
(string <var>)
--> INPUT OUTPUT <--
(write <term> ...)
(locate <iterm> <iterm>)
(cls)
(window <iterm> <iterm> <iterm> <iterm> <sterm>)
(tell <sterm>) open a file for writing
(told) close file
(see <sterm>) open a file for reading
(seen) close file
(filelen <sterm>) get filelength
(readint) read an integer
(read <svar>) read a string
(get) read one character
(put <iterm>) write one character
(dump) show all variables
--> GRAPHICS <--
(line <iterm> <iterm> <iterm> <iterm> <iterm>)
(plot <iterm> <iterm> <iterm>)
(box <iterm> <iterm> <iterm> <iterm> <iterm>)
(text <iterm> <iterm> <iterm> <iterm> <sterm>)
(mousex), (mousey) intuition
(mouse) non-intuition
NEW IN VERSION 1.2:
- changes to existing functions:
(>) as equivalent for (greater)
(<) as equivalent for (smaller)
(array <var> <size> <iterm> ...) /* inits array with <iterm>s (opt) */
(set <stringvar> <sterm>)
- additional functions:
math etc.:
(abs <iterm>)
(mod <iterm> <iterm>) /* (mod 20 3) => 2 */
(eor <iterm> ...)
(swap <var> <var>) /* currently vars only */
(power <iterm> <iterm>) /* (power 2 5) => 32 */
(inc <var>)
(dec <var>)
system:
(kick <iterm>) /* (if (kick 37) ... ) */
(exit)
control:
(when <bterm> <term> ... /* (if <bterm> (do <term> ...) */
else <term> ...) /* (do <term> ...)) */
input/output:
(hex <iterm>) /* writes num in hexadecimal */
intuition:
(req <sterm> <sterm> <sterm>) /* (req 'YAX req' 'choose:' 'a|b|c') */
(screen w h d flags title) /* opens screen */
(win x y w h IDCMP flags title) /* opens gfx-only window and closes
any previous w. if (screen) was
used, (win) opens on it */
(gadget id x y width title) /* makes gadget on cur. window */
(message) /* Wait()s and returns IDCMP */
(gadid) /* returns gadnum in event */
NOTE: now that there's (win) and (screen), graphics and intuition
functions should not be used on windows opened with (window)
(these are for stdio only), it will be possible however to use
graphics functions on them for backward compatability with 1.1.
POSSIBLE ENHANCEMENTS:
- true lambda's for function calls
ben:
- string commands
- run another yax prog from yax code
- (see) twice --> problems? better file support.
- yax compiler (to E)
*/